package com.wyz.easyexcel.util;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.handler.WriteHandler;
import com.wyz.easyexcel.constant.RequestConstant;
import org.springframework.util.CollectionUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Collection;
import java.util.Optional;

/**
 * @author wyz
 * @description: 文件下载工具类
 * @date 2021/12/31 9:11
 */
public class FileDownloadUtils {

    private FileDownloadUtils(){}

    /**
     *  获取HttpServletResponse 对象
     * @return
     */
    public static HttpServletResponse getResponse(){
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletResponse httpServletResponse = Optional.ofNullable(requestAttributes).map(ServletRequestAttributes::getResponse)
                .orElseThrow(() -> new NullPointerException("该次请求线程中，获取HttpServletResponse对象时，为null"));
        return httpServletResponse;
    }

    /**
     *  采用默认下载
     * @param cls
     * @param fileName
     * @param sheetName
     * @param data
     * @throws IOException
     */
    public static void downLoad(Class cls, String fileName, String sheetName, Collection<?> data) throws IOException {
        downLoad(cls,fileName,sheetName,data,null,null);
    }

    /**
     *  有自定义处理器下载
     * @param cls
     * @param fileName
     * @param sheetName
     * @param data
     * @param handlers
     * @throws IOException
     */
    public static void downLoad(Class cls,String fileName, String sheetName, Collection<?> data, Collection<? extends WriteHandler> handlers) throws IOException {
        downLoad(cls,fileName,sheetName,data,handlers,null);
    }

    /**
     *  有动态过滤列字段的 下载文件
     * @param cls class 对象
     * @param fileName 文件名称
     * @param sheetName sheet
     * @param data 数据源
     * @param handlers 处理器
     * @param excludeColumnFiledNames 排除列字段名称  如果忽略的字段是固定的，
     *                                可以直接在实体类中要忽略的字段上加@ExcelIgnore即可，无需使用该集合
     * @throws IOException
     */
    public static void downLoad(Class cls, String fileName, String sheetName, Collection<?> data , Collection<? extends WriteHandler> handlers, Collection<String> excludeColumnFiledNames) throws IOException {
        HttpServletResponse response = getResponse();
        response.setContentType(RequestConstant.CONTENT_TYPE);
        response.setCharacterEncoding(RequestConstant.FILE_ENCODING);
        fileName = URLEncoder.encode(fileName, RequestConstant.FILE_ENCODING).replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        ExcelWriterBuilder excelWriterBuilder = EasyExcel.write(response.getOutputStream(), cls).excludeColumnFiledNames(excludeColumnFiledNames);
        if (!CollectionUtils.isEmpty(handlers)) {
            handlers.stream().forEach(writeHandler->excelWriterBuilder.registerWriteHandler(writeHandler));
        }
        excelWriterBuilder.sheet(sheetName).doWrite(data);
    }

    /**
     *  有动态过滤列字段的 下载文件
     * @param cls class 对象
     * @param fileName 文件名称
     * @param sheetName sheet
     * @param passWord 密码
     * @param data 数据源
     * @param handlers 处理器
     * @param excludeColumnFiledNames 排除列字段名称  如果忽略的字段是固定的，
     *                                可以直接在实体类中要忽略的字段上加@ExcelIgnore即可，无需使用该集合
     * @throws IOException
     */
    public static void downLoad(Class cls, String fileName, String sheetName,String passWord, Collection<?> data , Collection<? extends WriteHandler> handlers, Collection<String> excludeColumnFiledNames) throws IOException {
        HttpServletResponse response = getResponse();
        response.setContentType(RequestConstant.CONTENT_TYPE);
        response.setCharacterEncoding(RequestConstant.FILE_ENCODING);
        fileName = URLEncoder.encode(fileName, RequestConstant.FILE_ENCODING).replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        ExcelWriterBuilder excelWriterBuilder = EasyExcel.write(response.getOutputStream(), cls).excludeColumnFiledNames(excludeColumnFiledNames).password(passWord);
        if (!CollectionUtils.isEmpty(handlers)) {
            handlers.stream().forEach(writeHandler->excelWriterBuilder.registerWriteHandler(writeHandler));
        }
        excelWriterBuilder.sheet(sheetName).doWrite(data);
    }
}
